/*
 * Bloque.cpp
 *
 *  Created on: 25/09/2010
 *      Author: damian
 */

#include "Bloque.h"

Bloque::Bloque(int numeroBloque, int tamanioBloque, int espacioOcupado, fstream* archivo) {




	this->setNumeroBloque(numeroBloque);
	this->setTamanioBloque(tamanioBloque);

	this->setArchivo(archivo);


	this->setEspacioLibre(tamanioBloque - espacioOcupado);



	// TODO checkear esto q bardea bastante
	this->setMemoria(new char(tamanioBloque));

	stringstream ios(ios_base::in| ios_base::out| ios_base::binary);

	int offset = (numeroBloque * tamanioBloque);
	ManejadorArchivo::RecuperarEstructura(archivo,&ios,offset, tamanioBloque + offset);

	ios.read(this->getMemoria(), tamanioBloque);

}

Bloque::Bloque(int numeroBloque, int tamanioBloque, char* mailSerializado, fstream* archivo){

	cout << "........." << endl;
	cout << "Asignando Valores..." << endl;

	this->setNumeroBloque(numeroBloque);
	cout << "Asignado Nro Bloque..." << endl;

	this->setTamanioBloque(tamanioBloque);
	cout << "Asignado Tamaño Bloque..." << endl;

	this->setArchivo(archivo);
	cout << "Asignado Archivo..." << endl;

	this->setEspacioLibre(tamanioBloque);
	cout << "Asignado Espacio Libre..." << endl;

	char* nuevaMemoria = new char[tamanioBloque];

	for (int i = 0; i < tamanioBloque; i++){
		nuevaMemoria[i] = '0';
	}

	this->setMemoria(nuevaMemoria);

	cout << "Creada Memoria de " << strlen(this->getMemoria()) << "bytes" << endl;


	cout << numeroBloque << endl;
	cout << tamanioBloque << endl;
	cout << this->getEspacioLibre() << endl;
	cout << "--------------" << endl;

	//stringstream ios(ios_base::in| ios_base::out| ios_base::binary);
	int offset = (numeroBloque * tamanioBloque);

	cout << "offset: " << offset << endl;

	cout << "Almacenando Mail: " << mailSerializado << endl;
	this->almacenarMail(mailSerializado);

	//TODO ya esta en almacenar mail..  check it..
//	cout << "Persistiendo Bloque..."<< endl;
//	this->persistirBloque();

}

int Bloque::getEspacioLibre() const
{
    return espacioLibre;
}

void Bloque::setEspacioLibre(int EspacioLibre)
{
    this->espacioLibre = EspacioLibre;
}

bool Bloque::persistirBloque(){

	stringstream ios(ios_base::in| ios_base::out| ios_base::binary);
	int offset = (this->getNumeroBloque() * this->getTamanioBloque());

	ios.write(this->getMemoria(),this->getTamanioBloque());
	return 	ManejadorArchivo::EscribirEstructura(this->getArchivo(), &ios,offset , this->getTamanioBloque());

	cout << "Bloque Persistido" << endl;
}

bool Bloque::almacenarMail(char* mailSerializado){

	//TODO CHECKEADO AFUERA?

			int espacioOcupado = (this->getTamanioBloque() - this->getEspacioLibre());

			cout << endl << "[][][][][][][][][][]" << endl;
			cout << espacioOcupado << endl;

			memcpy((this->getMemoria()+espacioOcupado),mailSerializado,strlen(mailSerializado));

			cout << "Getting Memoria" << endl;
			cout << this->getMemoria() << endl;

			this->persistirBloque();

			return true;

}

void Bloque::actualizarEspacioLibre(int cambioTamanio){

	this->setEspacioLibre((this->getEspacioLibre()+cambioTamanio));

}


int Bloque::getLongitudCorreo(int offset){

	//TODO Check this dude..

	int tamanioOrigen = TransformUnsignedCharToInt((unsigned char *)&this->getMemoria()[offset],2);

	int tamanioDestinatarios = TransformUnsignedCharToInt((unsigned char *)&this->getMemoria()[18],4);

	int tamanioMensaje = TransformUnsignedCharToInt((unsigned char *)&this->getMemoria()[23],4);

	int tamanioAsunto = this->getMemoria()[22];

	int tamanioCorreoConMetadata = 0;
	tamanioCorreoConMetadata = tamanioOrigen + tamanioDestinatarios + tamanioAsunto + tamanioMensaje + strlen(this->getMemoria());

	return tamanioCorreoConMetadata;

}

int Bloque::TransformUnsignedCharToInt(unsigned char* metadata, int cantidadChars){

	int entero = 0;

	switch (cantidadChars)
	{
	case 2:

		if (metadata[1]!=0)
		{
			entero = (metadata[1]<<8)|(metadata[0]<<0)|entero;
		}
		else
			entero += metadata[0];
		return entero;

	case 4:
		if(metadata[1]!=0 || metadata[2]!=0 || metadata[3]!=0)
		{

			entero = (metadata[3]<<24)|(metadata[2]<<16)|(metadata[1]<<8)|(metadata[0]<<0)|entero;
		}
		else
			entero=metadata[0];
		return entero;

	default: return 0;

	}

}

char* Bloque::obtenerMail(IUC* iuc){

	int offset = 0;
	char* iucLeido = new char[strlen(iuc->getId())];
	char* iucBuscado = iuc->getId();
	bool encontrado = false;


	memcpy(iucLeido,&(this->getMemoria()[offset]),strlen(iuc->getId()));

	encontrado = (strcmp(iucLeido,iucBuscado) == 0);


	while (!encontrado){

	offset = offset + this->getLongitudCorreo(offset);

	memcpy(iucLeido,&(this->getMemoria()[offset]),strlen(iuc->getId()));

	encontrado = (strcmp(iucLeido,iucBuscado) == 0);

	}

	if (encontrado) {
		int tamanioMailEncontrado = this->getLongitudCorreo(offset);
		char* mailEncontrado = new char[tamanioMailEncontrado];

		memcpy(mailEncontrado,&(this->getMemoria()[offset]),tamanioMailEncontrado);

		return mailEncontrado;


	}else return NULL;

}

char* Bloque::obtenerMail(int iuc){

	int offset = 0;

	cout << "Hola, estoy aca 0" << endl;


	char* iucLeido = new char[sizeof(iuc)];

	cout << "Hola, estoy aca 1" << endl;

	for (unsigned int i = 0; i < sizeof(iuc); i++){
		iucLeido[i] = '0';
	}

	cout << "Hola, estoy aca 2" << endl;


	cout << "------------------------" << endl;

	char* iucBuscado = (reinterpret_cast<char*>(&iuc));//new char[sizeof(iuc)];

	iucBuscado = reinterpret_cast<char*>(iuc);

/*	for (int i = 0; i < sizeof(iuc); i++){

		iucBuscado[i] = iuc[i];

	}
*/


	cout << "IUC Leido: " << iucLeido << endl
		 << "IUC Buscado: " << iucBuscado << endl;

	bool encontrado = false;


	memcpy(iucLeido,&(this->getMemoria()[offset]),strlen((char*)iuc));

	encontrado = (strcmp(iucLeido,iucBuscado) == 0);


	while (!encontrado){

	offset = offset + this->getLongitudCorreo(offset);

	memcpy(iucLeido,&(this->getMemoria()[offset]),strlen((char*)iuc));

	encontrado = (strcmp(iucLeido,iucBuscado) == 0);

	}

	if (encontrado) {
		int tamanioMailEncontrado = this->getLongitudCorreo(offset);
		char* mailEncontrado = new char[tamanioMailEncontrado];

		memcpy(mailEncontrado,&(this->getMemoria()[offset]),tamanioMailEncontrado);

		return mailEncontrado;


	}else return NULL;

}


char* Bloque::getMemoria()
{
    return memoria;
}

int Bloque::getNumeroBloque()
{
    return numeroBloque;
}

int Bloque::getTamanioBloque()
{
    return tamanioBloque;
}

void Bloque::setMemoria(char *memoria)
{
	this->memoria = memoria;
}

void Bloque::setNumeroBloque(int numeroBloque)
{
    this->numeroBloque = numeroBloque;
}

fstream *Bloque::getArchivo()
{
    return archivo;
}

void Bloque::setArchivo(fstream *archivo)
{
    this->archivo = archivo;
}

void Bloque::setTamanioBloque(int tamanioBloque)
{
    this->tamanioBloque = tamanioBloque;
}

Bloque::~Bloque() {
	// TODO Auto-generated destructor stub
}

